#include "common.h"
#include "msn_command.h"

static char *msn_ns_command_type_string(int type);
static char * msn_sb_command_type_string(int type) ;

int msn_ns_command_type_get(const char *line, const int line_size)
{
	if(!line)
		return MSN_NS_NONE;
	int type = MSN_NS_NONE;

	if(!strncmp(line, "MSG ", 4))
		type = MSN_NS_MSG;
	else if(!strncmp(line, "BLP ", 4))
		type = MSN_NS_BLP;
	else if(!strncmp(line, "USR ", 4))
		type = MSN_NS_USR;
	else if(!strncmp(line, "ADL ", 4))
		type = MSN_NS_ADL;
	else if(!strncmp(line, "PRP ", 4))
		type = MSN_NS_PRP;
	else if(!strncmp(line, "CHG ", 4))
		type = MSN_NS_CHG;
	else if(!strncmp(line, "UBX ", 4))
		type = MSN_NS_UBX;
	else if(!strncmp(line, "RNG ", 4))
		type = MSN_NS_RNG;
	else if(!strncmp(line, "CHL ", 4))
		type = MSN_NS_CHL;
	else if(!strncmp(line, "QRY ", 4))
		type = MSN_NS_QRY;
	else if(!strncmp(line, "QNG ", 4))
		type = MSN_NS_QNG;
	else if(!strncmp(line, "VER ", 4))
		type = MSN_NS_VER;
	else if(!strncmp(line, "CVR ", 4))
		type = MSN_NS_CVR;
	else if(!strncmp(line, "XFR ", 4))
		type = MSN_NS_XFR;
	else if(!strncmp(line, "GCF ", 4))
		type = MSN_NS_GCF;

	debug_log(9, "command type %s\n", msn_ns_command_type_string(type));
	return type;
}

static char *msn_ns_command_type_string(int type)
{
	switch(type) {
		case MSN_NS_MSG:
			return "MSG";
		case MSN_NS_BLP:
			return "BLP";
		case MSN_NS_USR:
			return "USR";
		case MSN_NS_ADL:
			return "ADL";
		case MSN_NS_PRP:
			return "PRP";
		case MSN_NS_CHG:
			return "CHG";
		case MSN_NS_UBX:
			return "UBX";
		case MSN_NS_RNG:
			return "RNG";
		case MSN_NS_CHL:
			return "CHL";
		case MSN_NS_QRY:
			return "QRY";
		case MSN_NS_QNG:
			return "QNG";
		case MSN_NS_CVR:
			return "CVR";
		case MSN_NS_VER:
			return "VER";
		case MSN_NS_XFR:
			return "XFR";
		case MSN_NS_GCF:
			return "GCF";
		default:
			return "NONE";
	}
}

static char * msn_sb_command_type_string(int type) 
{
	switch(type) {
		case MSN_SB_ANS:
			return "ANS";
		case MSN_SB_MSG:
			return "MSG";
		case MSN_SB_BYE:
			return "BYE";
		case MSN_SB_USR:
			return "USR";
		default: 
			return "NONE";
	}
}

int msn_command_payload(const char *line, const int line_size)
{
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int payload = 0;
	
	debug_log(9, "%d bytes {%s}\n", line_size, line);
	if(!line)
		return;
	assert(line_size < MAX_BUFFER);
	memcpy(buf, line, line_size);
	buf[line_size] = '\0';
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last)) {
		debug_log(9, "token '%s'\n", token);
		pre = token;
	}
	assert(pre);
	payload = atoi(pre);
	debug_log(8, "payload %d\n", payload);
	return payload;
}

int msn_sb_command_type_get(const char *line, const int size)
{
	if(!line)
		return MSN_SB_NONE;
	int type = MSN_SB_NONE;

	if(!strncmp(line, "ANS ", 4))
		type = MSN_SB_ANS;
	else if(!strncmp(line, "MSG ", 4))
		type = MSN_SB_MSG;
	else if(!strncmp(line, "BYE ", 4))
		type = MSN_SB_BYE;
	else if(!strncmp(line, "USR ", 4))
		type = MSN_SB_USR;

	debug_log(9, "command type %s\n", msn_sb_command_type_string(type));
	return type;
}

void msn_sb_msg_parse(const char *line, const int size, GString *passport, \
				GString *display, int *payload)
{
	assert(passport && display);
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int i = 0;
	gsize br, bw;
	
	if(!line)
		return;
	memcpy(buf, line, size);
	buf[size] = '\0';
	debug_log(9, "%d bytes {%s}\n", size, line);
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last), i++) {
		debug_log(9, "token '%s'\n", token);
		if(i == 1) {
			g_string_append(passport, token);
		}
		else if( i == 2) 
			g_string_append(display, token);
		else if(i == 3) 
			*payload = atoi(token);
	}
}

void msn_ns_adl_parse(const char *line, const int size, int *payload)
{
	if(!line)
		return;
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int i = 0;
	
	debug_log(9, "%d bytes {%s}\n", size, line);
	if(!line)
		return;
	assert(size < MAX_BUFFER);
	memcpy(buf, line, size);
	buf[size] = '\0';
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last), i++) {
		debug_log(9, "token '%s'\n", token);
		if( i == 2) {
			if(!strcasecmp(token, "ok")) {
				debug_log(9, "It is %s\n", token);
				break;
			}
			*payload = atoi(token);
		}
	}
}

void msn_ns_qng_parse(const char *line, const int size, int *time)
{
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int i = 0;
	
	debug_log(9, "%d bytes {%s}\n", size, line);
	if(!line)
		return;
	assert(size < MAX_BUFFER);
	memcpy(buf, line, size);
	buf[size] = '\0';
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last), i++) {
		debug_log(9, "token '%s'\n", token);
		if( i == 1) {
			*time = atoi(token);
		}
	}
}

void msn_command_send(event_t *ev, int fd, void *arg, \
			   void (*cb) (int, int, int, void *),	const char *fmt, ...)
{
	GString *out = NULL;
	va_list  va;

	g_return_if_fail(ev != NULL);
	out = g_string_new(NULL);
	va_start(va, fmt);
	g_string_vprintf(out, fmt, va);
	va_end(va);
	debug_log(6, "Send command %d bytes, {%s}\n", out->len, out->str);
	sock_write(ev,  fd, cb, arg, out);
	g_string_free(out, 1);
}

void msn_ns_xfr_parse(const char *line, const int size, int *isns, char *ip, int *port)
{
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int i = 0;
	
	debug_log(9, "%d bytes {%s}\n", size, line);
	if(!line)
		return;
	assert(size < MAX_BUFFER);
	memcpy(buf, line, size);
	buf[size] = '\0';
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last), i++) {
		debug_log(9, "token '%s'\n", token);
		if( i == 2) {
			if(!strcasecmp("ns", token)) 
				*isns = 1;
		}
		else if(i == 3) 
			sock_ip_port_parse(token, ip, port);
	}
}

void msn_ns_usr_parse(const char *line, const int size, char *nonce)
{
	char *token, *last, *pre;
	const char *sep = " \t\n\r";
	char buf[MAX_BUFFER];
	int i = 0;
	
	debug_log(9, "%d bytes {%s}\n", size, line);
	if(!line)
		return;
	assert(size < MAX_BUFFER);
	memcpy(buf, line, size);
	buf[size] = '\0';
	for(token = strtok_r(buf, sep, &last); token; token = strtok_r(NULL, sep, &last), i++) {
		debug_log(9, "token '%s'\n", token);
		if( i == 2) {
			if(!strcasecmp("ok", token)) 
				return;
		}
		else if(i == 5) 
			strcpy(nonce, token);
	}
	
}
